<!DOCTYPE html>
<!-- saved from url=(0127)https://docs.google.com/document/d/e/2PACX-1vRDw9imr6RoHWdiGyJOaK0HHh_KZstEYsQdR2y_uvZGHUdqQp2s-W6_3Pg1q6rr4Zhl85csQuugXQxH/pub -->
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>WebPerfWG call - May 12th 2021</title><link rel="shortcut icon" href="https://ssl.gstatic.com/docs/documents/images/kix-favicon7.ico"><meta name="referrer" content="strict-origin-when-cross-origin"><style type="text/css" nonce="">
      @import url("https://fonts.googleapis.com/css?family=Google+Sans");
      @import url("https://fonts.googleapis.com/css?family=Roboto");

      body {
        font-family: Roboto, arial, sans, sans-serif;
        margin: 0;
      }

      iframe {
        border: 0;
        frameborder: 0;
        height: 100%;
        width: 100%;
      }

      #header {
        align-items: center;
        background: white;
        border-bottom: 1px #ccc solid;
        display: flex;
        height: 60px;
        justify-content: space-between;
        position: fixed;
        top: 0;
        width: 100%;
        z-index: 100;
      }

      #header #title {
        font-family: 'Google Sans';
        font-size: large;
        margin: auto 0 auto 20px;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        width: 70%;
      }

      #header #interval {
        margin: auto 25px auto 0;
        font-family: Roboto;
        font-size: small;;
      }

      #footer {
        background: #f0f0f0;
        border-bottom: 1px #ccc solid;
        bottom: 0;
        font-family: Roboto;
        font-size: small;
        padding: 10px 10px;
        position: fixed;
        text-align: center;
        width: 100%;
      }

      #contents {
        padding: 100px 20% 50px 20%;
      }

      @media only screen and (max-device-width: 800px) {
        #header {
          border-bottom-width: 5px;
          height: auto;
          display: block;
        }

        #header #title {
          font-size: 3em;
          margin: auto 0 auto 20px;
          width: 90%;
        }

        #header #interval {
          font-size: 1.5em;
          margin: 10px 0 auto 25px;
        }

        #contents {
          padding: 150px 5% 80px;
        }

        #footer {
          font-size: 2em;
        }
      }

      .dash {
        padding: 0 6px;
      }
    </style></head><body><div id="header"><div id="title">WebPerfWG call - May 12th 2021</div><div id="interval"><span></span></div></div><div id="contents"><style type="text/css">.lst-kix_mim74plagep0-4>li:before{content:"\0025cb  "}.lst-kix_mim74plagep0-2>li:before{content:"\0025a0  "}.lst-kix_mim74plagep0-6>li:before{content:"\0025cf  "}.lst-kix_mim74plagep0-1>li:before{content:"\0025cb  "}.lst-kix_mim74plagep0-5>li:before{content:"\0025a0  "}.lst-kix_mim74plagep0-3>li:before{content:"\0025cf  "}.lst-kix_mim74plagep0-8>li:before{content:"\0025a0  "}.lst-kix_bgr341i17le1-4>li:before{content:"\0025cb  "}.lst-kix_avsezgk4ojd7-4>li:before{content:"\0025cb  "}.lst-kix_avsezgk4ojd7-3>li:before{content:"\0025cf  "}.lst-kix_bgr341i17le1-5>li:before{content:"\0025a0  "}.lst-kix_bgr341i17le1-6>li:before{content:"\0025cf  "}.lst-kix_mim74plagep0-7>li:before{content:"\0025cb  "}.lst-kix_avsezgk4ojd7-1>li:before{content:"\0025cb  "}ul.lst-kix_avsezgk4ojd7-4{list-style-type:none}ul.lst-kix_avsezgk4ojd7-5{list-style-type:none}.lst-kix_avsezgk4ojd7-0>li:before{content:"\0025cf  "}.lst-kix_avsezgk4ojd7-2>li:before{content:"\0025a0  "}ul.lst-kix_avsezgk4ojd7-2{list-style-type:none}ul.lst-kix_avsezgk4ojd7-3{list-style-type:none}ul.lst-kix_avsezgk4ojd7-0{list-style-type:none}ul.lst-kix_avsezgk4ojd7-1{list-style-type:none}.lst-kix_bgr341i17le1-3>li:before{content:"\0025cf  "}.lst-kix_bgr341i17le1-1>li:before{content:"\0025cb  "}.lst-kix_bgr341i17le1-2>li:before{content:"\0025a0  "}.lst-kix_bgr341i17le1-0>li:before{content:"\0025cf  "}ul.lst-kix_avsezgk4ojd7-8{list-style-type:none}ul.lst-kix_avsezgk4ojd7-6{list-style-type:none}ul.lst-kix_avsezgk4ojd7-7{list-style-type:none}.lst-kix_bgr341i17le1-7>li:before{content:"\0025cb  "}.lst-kix_bgr341i17le1-8>li:before{content:"\0025a0  "}ul.lst-kix_bgr341i17le1-7{list-style-type:none}ul.lst-kix_bgr341i17le1-8{list-style-type:none}ul.lst-kix_bgr341i17le1-5{list-style-type:none}ul.lst-kix_bgr341i17le1-6{list-style-type:none}.lst-kix_avsezgk4ojd7-5>li:before{content:"\0025a0  "}.lst-kix_avsezgk4ojd7-6>li:before{content:"\0025cf  "}.lst-kix_avsezgk4ojd7-7>li:before{content:"\0025cb  "}li.li-bullet-0:before{margin-left:-18pt;white-space:nowrap;display:inline-block;min-width:18pt}.lst-kix_avsezgk4ojd7-8>li:before{content:"\0025a0  "}ul.lst-kix_mim74plagep0-8{list-style-type:none}ul.lst-kix_mim74plagep0-7{list-style-type:none}ul.lst-kix_mim74plagep0-6{list-style-type:none}ul.lst-kix_mim74plagep0-5{list-style-type:none}ul.lst-kix_mim74plagep0-4{list-style-type:none}.lst-kix_mim74plagep0-0>li:before{content:"\0025cf  "}ul.lst-kix_mim74plagep0-3{list-style-type:none}ul.lst-kix_bgr341i17le1-3{list-style-type:none}ul.lst-kix_mim74plagep0-2{list-style-type:none}ul.lst-kix_bgr341i17le1-4{list-style-type:none}ul.lst-kix_mim74plagep0-1{list-style-type:none}ul.lst-kix_bgr341i17le1-1{list-style-type:none}ul.lst-kix_mim74plagep0-0{list-style-type:none}ul.lst-kix_bgr341i17le1-2{list-style-type:none}ul.lst-kix_bgr341i17le1-0{list-style-type:none}ol{margin:0;padding:0}table td,table th{padding:0}.c0{margin-left:36pt;padding-top:0pt;padding-left:0pt;padding-bottom:0pt;line-height:1.15;orphans:2;widows:2;text-align:left}.c7{color:#434343;font-weight:400;text-decoration:none;vertical-align:baseline;font-size:14pt;font-family:"Arial";font-style:normal}.c10{padding-top:18pt;padding-bottom:6pt;line-height:1.15;page-break-after:avoid;orphans:2;widows:2;text-align:left}.c2{color:#000000;font-weight:400;text-decoration:none;vertical-align:baseline;font-size:16pt;font-family:"Arial";font-style:normal}.c8{padding-top:16pt;padding-bottom:4pt;line-height:1.15;page-break-after:avoid;orphans:2;widows:2;text-align:left}.c3{color:#000000;font-weight:400;text-decoration:none;vertical-align:baseline;font-size:11pt;font-family:"Arial";font-style:normal}.c9{padding-top:0pt;padding-bottom:0pt;line-height:1.15;orphans:2;widows:2;text-align:left}.c1{text-decoration-skip-ink:none;-webkit-text-decoration-skip:none;color:#1155cc;text-decoration:underline}.c5{background-color:#ffffff;max-width:468pt;padding:72pt 72pt 72pt 72pt}.c4{color:inherit;text-decoration:inherit}.c6{padding:0;margin:0}.c11{height:11pt}.title{padding-top:0pt;color:#000000;font-size:26pt;padding-bottom:3pt;font-family:"Arial";line-height:1.15;page-break-after:avoid;orphans:2;widows:2;text-align:left}.subtitle{padding-top:0pt;color:#666666;font-size:15pt;padding-bottom:16pt;font-family:"Arial";line-height:1.15;page-break-after:avoid;orphans:2;widows:2;text-align:left}li{color:#000000;font-size:11pt;font-family:"Arial"}p{margin:0;color:#000000;font-size:11pt;font-family:"Arial"}h1{padding-top:20pt;color:#000000;font-size:20pt;padding-bottom:6pt;font-family:"Arial";line-height:1.15;page-break-after:avoid;orphans:2;widows:2;text-align:left}h2{padding-top:18pt;color:#000000;font-size:16pt;padding-bottom:6pt;font-family:"Arial";line-height:1.15;page-break-after:avoid;orphans:2;widows:2;text-align:left}h3{padding-top:16pt;color:#434343;font-size:14pt;padding-bottom:4pt;font-family:"Arial";line-height:1.15;page-break-after:avoid;orphans:2;widows:2;text-align:left}h4{padding-top:14pt;color:#666666;font-size:12pt;padding-bottom:4pt;font-family:"Arial";line-height:1.15;page-break-after:avoid;orphans:2;widows:2;text-align:left}h5{padding-top:12pt;color:#666666;font-size:11pt;padding-bottom:4pt;font-family:"Arial";line-height:1.15;page-break-after:avoid;orphans:2;widows:2;text-align:left}h6{padding-top:12pt;color:#666666;font-size:11pt;padding-bottom:4pt;font-family:"Arial";line-height:1.15;page-break-after:avoid;font-style:italic;orphans:2;widows:2;text-align:left}</style><div class="c5"><h2 class="c10" id="h.jaryppsvwdw5"><span class="c2">Participants</span></h2><p class="c9"><span class="c3">Yoav Weiss, Jonathan Mayer, Michal Mocny, Nicol&aacute;s Pe&ntilde;a Moreno, Hongbo Song, Andrew Galloni, Sean Feng, Benjamin De Kosnik</span></p><p class="c9 c11"><span class="c3"></span></p><h2 class="c10" id="h.ar9905iz2ptw"><span class="c2">Next Meeting</span></h2><p class="c9"><span class="c3">Thursday May 27th, 10am PST / 1pm EST</span></p><h2 class="c10" id="h.rzk110rqibzf"><span class="c2">Minutes</span></h2><h3 class="c8" id="h.s8oy75zdhe72"><span class="c1"><a class="c4" href="https://www.google.com/url?q=https://github.com/w3c/performance-timeline/issues/181&amp;sa=D&amp;source=editors&amp;ust=1623834675859000&amp;usg=AOvVaw3m6Tb7G1zCGHYNvMCsltL7">PerfTimeline #181: Should droppedEntriesCount be frozen on each observer?</a></span><span class="c7">&nbsp;</span></h3><ul class="c6 lst-kix_bgr341i17le1-0 start"><li class="c0 li-bullet-0"><span class="c3"><b>Nicol&aacute;s</b>: Looking to implementing droppedEntriesCount</span></li><li class="c0 li-bullet-0"><span class="c3">… Surfaces how many dropped entries</span></li><li class="c0 li-bullet-0"><span class="c3">… Is it confusing that the count increases on each callback?</span></li><li class="c0 li-bullet-0"><span class="c3">… Once buffer becomes full, each new entry will increase it even if you’re observing it</span></li><li class="c0 li-bullet-0"><span class="c3">… One potential solution is to freeze the number once it becomes non-zero</span></li><li class="c0 li-bullet-0"><span class="c3">… If it’s not zero in the first callback, you know you missed entries</span></li><li class="c0 li-bullet-0"><span class="c3">… If it becomes non-zero afterwards, you know when the buffer became full.</span></li><li class="c0 li-bullet-0"><span class="c3">… Wondered if people had thoughts?</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Michal</b>: Part of the problem with dropped buffers or cleared buffers, is that there could be different consumers of this API that could register observers at any time</span></li><li class="c0 li-bullet-0"><span class="c3">… If you froze it, it would be the same as the first observer</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Nicol&aacute;s</b>: I should clarify, it would be frozen for each observer, so different observers could get different numbers</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Michal</b>: Sounds fine. &nbsp;For event counts we get the total number of events. &nbsp;Instead of the number of dropped entries, we could give a total, and let developers infer if there were any dropped ones.</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Yoav</b>: What concerned me about current API shape where the number keeps growing over time, is that people will get confused </span></li><li class="c0 li-bullet-0"><span class="c3">… and despite the fact they registered an observer early on, they still have entries being “dropped” (even though they’re observing them)</span></li><li class="c0 li-bullet-0"><span class="c3">… On the consumer’s side of the API, would this be an issue?</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Nic</b>: Agree that if the number would keep growing it could lead to developers being confused about it. </span></li><li class="c0 li-bullet-0"><span class="c3">… Those in the know would get it, but it’d be a gotcha and we’d need to make sure people grok it. </span></li><li class="c0 li-bullet-0"><span class="c3">… Kinda like the idea of it being frozen. In our case we’d only be reading it in the beginning. </span></li><li class="c0 li-bullet-0"><span class="c3">… But I could see someone looking at their callback in devtools and being confused. Haven’t thought through it</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Andrew</b>: I agree, but need to think it through</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Nic</b>: Michal - was your thought of a total count being a global thing available?</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Michal</b>: Calling it numdropped would induce confusion as people would think that more entries were dropped but renaming it to total count would make it clear why the number grows, and we already do this elsewhere. </span></li><li class="c0 li-bullet-0"><span class="c3">… The 2 numbers are equivalent, because you have a fixed buffer size.</span></li><li class="c0 li-bullet-0"><span class="c3">… Could be a case that freezing the number would be confusing as well. A rename can help here as well</span></li><li class="c0 li-bullet-0"><span class="c3">… The advantage of having a dropped vs. total is that a non-zero value means that you have an incomplete observer, where the alternative requires more work, so it’s less obvious.</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Nic</b>: Agree with that</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Michal</b>: So for the specific use case, sounds like fixing it to the number of dropped entries at registration would be best</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Nicol&aacute;s</b>: Would we freeze it at zero or would it be useful to get a rough estimate of when the buffer became full?</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Nic</b>: So when observers register early and the buffer becomes full later?</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Nicol&aacute;s</b>: yeah</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Yoav</b>: theoretically, we could a separate method on `performance` to get the number of dropped entries, and decouple it entirely from PerfObserver. But that’d mean we don’t get a signal of when the buffer becomes full. Not sure that’s meaningful. </span></li><li class="c0 li-bullet-0"><span class="c3"><b>Nicol&aacute;s</b>: It becomes hard to know when you have to query to ensure you’re not missing entries. That’s why coupling it with the observer is useful.</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Michal</b>: If we’re going to freeze the number, is it useful to have a number?</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Nic</b>: It’s useful for RUM, could tell us how many entries we missed - 1000 entries would be a good argument to register earlier. There’s value in knowing the quantity</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Yoav</b>: What I’m hearing is that there’s general support for freezing the value, more than leaving it as is. </span></li><li class="c0 li-bullet-0"><span class="c3">… But the hurdle here is that in terms of shipping, the code is ready, but we don’t want to ship the wrong thing. Wondering what could give us more confidence. </span></li><li class="c0 li-bullet-0"><span>… </span><span>Nic and Andrew, can you think about this more and give us an answer?</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Andrew</b>: yeah</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Nic</b>: overall, the value is great. Need to think about the ergonomics. Can definitely think it through.</span></li></ul><h3 class="c8" id="h.g7efe14jzxb9"><span class="c1"><a class="c4" href="https://www.google.com/url?q=https://github.com/w3c/hr-time/issues/115&amp;sa=D&amp;source=editors&amp;ust=1623834675863000&amp;usg=AOvVaw36pxpSoq3aKPx520_P_4yz">HR-Time #115: Suggestions: ticking during sleep, comparison across contexts, time origin + now semantics, and skew definition</a></span><span class="c7">&nbsp;</span></h3><ul class="c6 lst-kix_avsezgk4ojd7-0 start"><li class="c0 li-bullet-0"><span class="c3"><b>Jonathan</b>: My research group at Princeton is using HRTime for a project that uses timing across web pages</span></li><li class="c0 li-bullet-0"><span class="c3">… Led to rabbit hole around looking at the history of the spec, hardware issues, etc</span></li><li class="c0 li-bullet-0"><span class="c3">… Four suggestions for possible revisions to spec</span></li><li class="c0 li-bullet-0"><span class="c3">… All I hope are very consistent with intent of spec</span></li><li class="c0 li-bullet-0"><span class="c3">… First is to clarify what behavior of what happens during system sleep</span></li><li class="c0 li-bullet-0"><span class="c3">… Second suggestion is to take an informative note (with SHOULD in it) and turning it into normative language. &nbsp;Turn suspending behavior into normative note, is to accomplish the goal of the spec. &nbsp;Compare monotonic timestamp across globals.</span></li><li class="c0 li-bullet-0"><span class="c3">… Third suggestion I’ll deal with last</span></li><li class="c0 li-bullet-0"><span class="c3">… In the issue, the fourth suggestion is just a terminology suggestion around “clock skew”, is different from how it’s normally used in computer science or electrical engineering</span></li><li class="c0 li-bullet-0"><span class="c3">… Third suggestion is clarifying semantics if you add performance.timeOrigin with performance.now. &nbsp;Zero guarantees how that’ll compare to system clock. </span></li><li class="c0 li-bullet-0"><span class="c3">... But there are some useful properties that could be defined. IIUC, browsers have already implemented the semantics I’m suggesting here, so hopefully it’s just reflecting semantics what browsers already provide rather than changing behavior</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Yoav</b>: Thank you for the issue, it’s well thought-out and articulated.</span></li><li class="c0 li-bullet-0"><span class="c3">… Useful information about various OSs and their clock behaviors</span></li><li class="c0 li-bullet-0"><span class="c3">… Suggestions for clarifying what we do in sleep mode, moving note to normative SHOULD make sense</span></li><li class="c0 li-bullet-0"><span class="c3">… Changing the terminology for clock skew - I think we could align with whatever the rest of the industry uses</span></li><li class="c0 li-bullet-0"><span class="c3">… For the semantics, I’m generally supportive but I wonder if this testable in some way</span></li><li class="c0 li-bullet-0"><span class="c3">… Similarly for sleep, I’m not sure we can have WPT tests for what happens when sleep</span></li><li class="c0 li-bullet-0"><span class="c3">… For semantics, we can’t enforce tests changing the clocks</span></li><li class="c0 li-bullet-0"><span class="c3">… Are there any objections to those clarifications? &nbsp;What do folks think about testing?</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Nicol&aacute;s</b>: Only problem is that most clocks seem to be not behaving properly during sleep according to the table. &nbsp;So the concern is that if we try to change the clocks, if they report internal metrics. &nbsp;Could risk some breakage.</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Yoav</b>: Do you expect that internal metrics are somehow relying on the fact that the freezing behavior is as it is right now?</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Nicol&aacute;s</b>: It seems on Windows they don’t rely on it, but I expect some metrics to shift in some ways in particular for high percentiles, because sleeps would count for longer portions of time instead of no portions of time</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Jonathan</b>: How this might be made easier for implementers, rather than changing underlying browser clock implementations, just adding another clock that has well-defined behavior. &nbsp;</span></li><li class="c0 li-bullet-0"><span class="c3">… Current users of the clock stay in place. &nbsp;But users that want the definition of the clock that continues during sleep could switch. There’s a Chrome design doc on that, and Firefox has a version of that in place.</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Yoav</b>: That would have a smoother migration process, but I’m not sure it reduces complexity</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Yoav</b>: Benjamin/Sean do you know what the situation is for Mozilla? Can Firefox align with this proposal.</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Benjamin</b>: I think this is doable. Are we talking about adding a performance.now monotonic clock option?</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Yoav</b>: This proposal doesn’t suggest an API change, just changing the semantics of performance.now() would say it SHOULD not freeze when table is throttled or frozen or the system is asleep, so the clock keeps ticking when any of those things happen</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Benjamin</b>: As opposed to not incrementing today?</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Yoav</b>: Current behavior on FF on Linux/Android, but not on Windows/Mac. &nbsp;Chromium only does that on Windows. &nbsp;Safari doesn’t do that anywhere.</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Nicol&aacute;s</b>: It’s already specified, but all browsers are behaving badly.</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Michal</b>: You’re saying there are two clocks in place on some platforms?</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Jonathan</b>: OS tend to provide monotonic multiple clock APIs that vary along at least two axis. &nbsp;Does the clock tick during system sleep or not? &nbsp;Is it subject to monotonic adjustments? &nbsp;</span></li><li class="c0 li-bullet-0"><span class="c3">… For example, your NTP client might figure out it’s off by a bit, can it adjust the clock or not?</span></li><li class="c0 li-bullet-0"><span class="c3">… That’s what OS offer. &nbsp;With respect to browsers, there’s one monotonic clock implementation across platforms. &nbsp;Firefox has 2-3 implementations in different places. &nbsp;One of which gives you the option to call the API with/without sleep included. &nbsp;Proposal for more implementations in Chrome.</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Benjamin</b>: I’d rather see this fully specified with both options, where it includes with-sleeps or with-adjustments</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Yoav</b>: You want to change the API so that a web developer add options to pick the clock they want?</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Benjamin</b>: What does a web developer get when they use it today, are we going to specify that in the spec?</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Yoav</b>: I’m not sure most web developers would care specifically, unless it’s for detecting sleep</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Nicol&aacute;s</b>: A while ago we decided sleep needs to tick. What was the reasoning?</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Yoav</b>: It can create a drift compared to date.now, and if we have multiples tabs that are frozen, comparing them can add confusion</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Nicol&aacute;s</b>: Are these clocks not using a shared infrastructure? Only a system sleep would make them all frozen or not frozen? If it’s possible for clocks to be frozen in some frames but not others, that would mean it’s impossible to compare timestamps across frames. </span></li><li class="c0 li-bullet-0"><span class="c3"><b>Yoav</b>: Issue 65 is mostly around frozen background tabs and clock skew in those cases, didn’t really discuss where the “entire system is in sleep mode” case.</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Jonathan</b>: To answer the question “Could you do this across webpages”, yes. &nbsp;The way the spec is currently drafted frozen tabs are combined with sleep. We could split the two.</span></li><li class="c0 li-bullet-0"><span class="c3">… I think it might be counterintuitive to have one behavior around frozen tabs vs. system sleep</span></li><li class="c0 li-bullet-0"><span class="c3">… Folks that are really familiar with Date.now() which ticks during sleep, if performance.now() was different could be confusing</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Michal</b>: Date.now() can “teleport”. Would users of Date.now() expect that the two would be in sync?</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Jonathan</b>: Our research group was confused about this. &nbsp;We thought, barring a user clock change, they’d be close if not identical, and that’s not the case.</span></li><li class="c0 li-bullet-0"><span class="c3">… You may want a timer that is monotonic and roughly approximate to real world time</span></li><li class="c0 li-bullet-0"><span class="c3">… For any precise timestamping of events across webpages that might be useful.</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Yoav</b>: Would be useful to account for time when the tab was frozen or the system was asleep. &nbsp;For things like user changing their clock there would be a difference between Date.now() and performance.now(). &nbsp;</span></li><li class="c0 li-bullet-0"><span class="c3">… Barring user changing clock, useful if the underlying time would be the same.</span></li><li class="c0 li-bullet-0"><span class="c3">… In my view I don’t see a strong use case to have the ability for web developers to pick the clock options.</span></li><li class="c0 li-bullet-0"><span class="c3">… It would have to be something not on top of performance.now, as it’s used in all the metrics. Maybe we can have a document policy that dictates what clock to use. I don’t necessarily see a strong use case though.</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Jonathan</b>: To add complexity, in addition to performance.now, you’d have to look at .timeOrigin, event.timestamp, etc, to make sure they’re all in sync.</span></li><li class="c0 li-bullet-0"><span><b>Benjamin</b>: Wondering if </span><span class="c1"><a class="c4" href="https://www.google.com/url?q=https://github.com/w3c/performance-timeline/issues/105&amp;sa=D&amp;source=editors&amp;ust=1623834675868000&amp;usg=AOvVaw0J6rRvTLtwKwBr_Ch0-Bsn">PT#105</a></span><span class="c3">&nbsp;might address this</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Yoav</b>: That seems orthogonal. This is a signal on backgrounding status and when tabs where backgrounded. If the clocks were to stop when tabs are backgrounded, that would move a lot of the metrics. Nicol&aacute;s, the VisibilityObserver effort is on hold, right?</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Nicol&aacute;s</b>: Yeah, there’s the VisibilityObserver discussion with open questions on prerendering, etc. </span></li><li class="c0 li-bullet-0"><span class="c3">… One reason you’d want clock frozen during sleep if you’re measuring time delta between two events. &nbsp;Clock would be super-long for no good reason, unless you know the tab froze, which is not something people do. </span></li><li class="c0 li-bullet-0"><span class="c3">… The hidden state may not work in sleep cases.</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Yoav</b>: No strong guarantees that visibility means the tab is frozen. It can be frozen after a timeout, etc. There can be implementation heuristics around that.</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Benjamin</b>: Wondering if there’s an opportunity to address both clarifications and adress unknown timer. Our timers right now are inconsistent when accounting for sleep or frozen times.</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Yoav</b>: Right now we can’t really rely on it because it’s different on different platforms and browsers. &nbsp;Would like to report timestamps for the time we spent in sleep. &nbsp;Have a “this tab was frozen” observer, or some indication to know this happened, so people can account for the lost time.</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Benjamin</b>: Add a frozen time to performance entries, or something, mark the gap somewhere in the timeline. Sounds like a good approach.</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Yoav</b>: We could start by aligning all the clocks, but it’d require implementations to do the leg work of implementing it. Appetite may depend on technical complexity. Nicol&aacute;s says it can get complex, so it may require some more research.</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Nicol&aacute;s</b>: We could talk to the Chrome folks that wrote the related doc. Good to try to align at least, we all have different behaviors, depending on what’s convenient to do in each OS. Not ideal.</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Jonathan</b>: While on the subject of different behaviors, there’s a deviation in Chrome/Firefox, timeOrigin is set a bit different than the spec.</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Yoav</b>: Useful to file implementation issues on that front</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Jonathan</b>: Filed issue in Chrome and Firefox bug trackers</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Benjamin</b>: If you haven’t already, link to it in the HRTime bug</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Yoav</b>: Thanks! We’re in agreement that it’d be great to make that happen. Now need to figure out how to get there.</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Benjamin</b>: Thanks for normalizing the term “skew”.</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Yoav</b>: Any proposals for other terms we could use.</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Jonathan</b>: “adjustment” would be fine. Giving examples of what’s permitted would help implementers: non-monotonic is not permitted, big adjustments not permitted, monotonic and small/gradual adjustments would be permitted. Just avoid the term “skew”.</span></li><li class="c0 li-bullet-0"><span class="c3">… Would be helpful to have a note on the OS options</span></li><li class="c0 li-bullet-0"><span class="c3"><b>Yoav</b>: That may be useful as a separate document, potentially. I haven’t seen other precedents for implementation hints as spec notes.</span></li><li class="c0 li-bullet-0"><span class="c3">… The issue itself is already useful on that front.</span></li></ul></div></div><div id="footer"><span>Published by <a target="_blank" title="Learn more about Google Drive" href="https://docs.google.com/">Google Drive</a></span><span class="dash">–</span><a href="https://docs.google.com/u/0/abuse?id=AKkXjoy1pL-2WGmnjRauCr_GcyU_wt1FdnZZ_nrt8EfLbeosUkM5k6lZY7LypqDEwwbeslOc9aUazvput6dCML4:0">Report Abuse</a></div><script type="text/javascript" nonce="">(function(){/*

 Copyright The Closure Library Authors.
 SPDX-License-Identifier: Apache-2.0
*/
var aa="function"==typeof Object.create?Object.create:function(a){function b(){}b.prototype=a;return new b},ba="function"==typeof Object.defineProperties?Object.defineProperty:function(a,b,c){if(a==Array.prototype||a==Object.prototype)return a;a[b]=c.value;return a};
function ca(a){a=["object"==typeof globalThis&&globalThis,a,"object"==typeof window&&window,"object"==typeof self&&self,"object"==typeof global&&global];for(var b=0;b<a.length;++b){var c=a[b];if(c&&c.Math==Math)return c}throw Error("Cannot find global object");}var da=ca(this);function ea(a,b){if(b)a:{var c=da;a=a.split(".");for(var d=0;d<a.length-1;d++){var e=a[d];if(!(e in c))break a;c=c[e]}a=a[a.length-1];d=c[a];b=b(d);b!=d&&null!=b&&ba(c,a,{configurable:!0,writable:!0,value:b})}}var h;
if("function"==typeof Object.setPrototypeOf)h=Object.setPrototypeOf;else{var l;a:{var fa={a:!0},ha={};try{ha.__proto__=fa;l=ha.a;break a}catch(a){}l=!1}h=l?function(a,b){a.__proto__=b;if(a.__proto__!==b)throw new TypeError(a+" is not extensible");return a}:null}var ia=h;
function m(a,b){a.prototype=aa(b.prototype);a.prototype.constructor=a;if(ia)ia(a,b);else for(var c in b)if("prototype"!=c)if(Object.defineProperties){var d=Object.getOwnPropertyDescriptor(b,c);d&&Object.defineProperty(a,c,d)}else a[c]=b[c];a.m=b.prototype}ea("Object.is",function(a){return a?a:function(b,c){return b===c?0!==b||1/b===1/c:b!==b&&c!==c}});var q=this||self;function r(){}function t(a){var b=typeof a;return"object"==b&&null!=a||"function"==b}
function ja(a,b){var c=Array.prototype.slice.call(arguments,1);return function(){var d=c.slice();d.push.apply(d,arguments);return a.apply(this,d)}}function ka(a,b){function c(){}c.prototype=b.prototype;a.m=b.prototype;a.prototype=new c;a.prototype.constructor=a;a.A=function(d,e,f){for(var g=Array(arguments.length-2),k=2;k<arguments.length;k++)g[k-2]=arguments[k];return b.prototype[e].apply(d,g)}}function u(a){return a};function w(a){w[" "](a);return a}w[" "]=r;function la(a,b,c){return Object.prototype.hasOwnProperty.call(a,b)?a[b]:a[b]=c(b)};function ma(a){return la(a.prototype,"$$generatedClassName",function(){return"Class$obf_"+{valueOf:function(){return++na}}})}var na=1E3;function x(){}x.prototype.s=function(){return this.j||(Object.defineProperties(this,{j:{value:oa=oa+1|0,enumerable:!1}}),this.j)};x.prototype.toString=function(){var a=y(z(pa(this.constructor)))+"@";var b=(this.s()>>>0).toString(16);return a+y(b)};function A(){}m(A,x);A.prototype.i=function(a){this.h=a;if(a instanceof Object)try{a.v=this}catch(b){}};function qa(a){a.h instanceof Error&&(Error.captureStackTrace?Error.captureStackTrace(a.h):a.h.stack=Error().stack)}A.prototype.toString=function(){var a=z(pa(this.constructor)),b=this.l;return null==b?a:y(a)+": "+y(b)};function B(){}m(B,A);function D(){}m(D,B);function E(){}m(E,D);E.prototype.i=function(a){D.prototype.i.call(this,Object.is(this.g,"__noinit__")?a:this.g)};function ra(){}m(ra,E);var oa=0;function sa(a,b){return"string"==typeof a?a.charCodeAt(b):a.g(b)};function y(a){return null==a?"null":a.toString()}function ta(a){return 65536<=a?y(String.fromCharCode((55296+((a-65536|0)>>10&1023)|0)&65535))+y(String.fromCharCode((56320+((a-65536|0)&1023)|0)&65535)):String.fromCharCode(a&65535)}function ua(a,b){var c=b,d=a.length,e;b=sa(a,(e=c,c=c+1|0,e));var f;if(e=55296<=b&&56319>=b&&c<d)a=f=sa(a,c),e=56320<=a&&57343>=a;var g;e?g=65536+((b&1023)<<10)+(f&1023)|0:g=b;return g};function F(a,b){this.g=a;this.h=b}m(F,x);function z(a){if(0!=a.h){var b="L"+y(ma(a.g))+";";a=a.h;for(var c="",d=0;d<a;d=d+1|0)c=y(c)+"[";return y(c)+y(b)}return ma(a.g)}F.prototype.toString=function(){return"class "+y(z(this))};function pa(a){return la(a.prototype,"$$class/0",function(){return new F(a,0)})};function G(a,b){return null==a?a:b?decodeURI(a):decodeURIComponent(a)};var va=/^(?:([^:/?#.]+):)?(?:\/\/(?:([^/?#]*)@)?([^/#?]*?)(?::([0-9]+))?(?=[/#?]|$))?([^?#]+)?(?:\?([^#]*))?(?:#([\S\s]*))?$/;function wa(a){a=va.exec(a);for(var b=[],c=0;7>=c;c=c+1|0)a.length<=c||null==a[c]?b.push(null):b.push(a[c]);return b}
function xa(a,b){var c=a.indexOf(ta(35));c=0>c?a.length:c;a:{var d=0;for(var e=b.length;0<(d=a.indexOf(b,d))&&d<c;){var f=ua(a,d-1|0);if(38==f||63==f){if((d+e|0)>=a.length)break a;f=ua(a,d+e|0);if(61==f||38==f||35==f)break a}d=d+(e+1)|0}d=-1}if(0>d)return null;e=a.indexOf(ta(38),d);if(0>e||e>c)e=c;d=d+(b.length+1)|0;b=Math.min(a.length,d);a=a.substr(b,Math.min(a.length,Math.max(d,e))-b|0);c=" ";for(b=0;0<=(b=c.indexOf("\\",b));)36==c.charCodeAt(b+1|0)?(d=y(c.substr(0,b|0))+"$",e=b=b+1|0,c=d+y(c.substr(e))):
(d=y(c.substr(0,b|0)),e=b=b+1|0,c=d+y(c.substr(e)));a=a.replace(/\+/g,c);return G(a,!1)};function ya(a){a&&"function"==typeof a.u&&a.u()};function H(){this.h=this.h;this.g=this.g}H.prototype.h=!1;H.prototype.u=function(){this.h||(this.h=!0,this.j())};H.prototype.j=function(){if(this.g)for(;this.g.length;)this.g.shift()()};var za=Array.prototype.indexOf?function(a,b){return Array.prototype.indexOf.call(a,b,void 0)}:function(a,b){if("string"===typeof a)return"string"!==typeof b||1!=b.length?-1:a.indexOf(b,0);for(var c=0;c<a.length;c++)if(c in a&&a[c]===b)return c;return-1};var Aa=/&/g,Ba=/</g,Ca=/>/g,Da=/"/g,Ea=/'/g,Fa=/\x00/g,Ga=/[\x00&<>"']/;var I;a:{var Ha=q.navigator;if(Ha){var Ia=Ha.userAgent;if(Ia){I=Ia;break a}}I=""}function J(a){return-1!=I.indexOf(a)};function Ja(a,b,c){for(var d in a)b.call(c,a[d],d,a)};var K;function L(a,b){this.i=a===Ka&&b||"";this.j=La}L.prototype.h=!0;L.prototype.g=function(){return this.i};var La={},Ka={};function M(a,b){this.i=b===N?a:""}M.prototype.h=!0;M.prototype.g=function(){return this.i.toString()};M.prototype.toString=function(){return this.i.toString()};function O(a){return a instanceof M&&a.constructor===M?a.i:"type_error:SafeUrl"}
var Ma=/^(?:audio\/(?:3gpp2|3gpp|aac|L16|midi|mp3|mp4|mpeg|oga|ogg|opus|x-m4a|x-matroska|x-wav|wav|webm)|font\/\w+|image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp|x-icon)|video\/(?:mpeg|mp4|ogg|webm|quicktime|x-matroska))(?:;\w+=(?:\w+|"[\w;,= ]+"))*$/i,Na=/^data:(.*);base64,[a-z0-9+\/]+=*$/i,Oa=/^(?:(?:https?|mailto|ftp):|[^:/?#]*(?:[/?#]|$))/i;function Pa(a){if(a instanceof M)return a;a="object"==typeof a&&a.h?a.g():String(a);Oa.test(a)||(a="about:invalid#zClosurez");return new M(a,N)}
var N={},Qa=new M("about:invalid#zClosurez",N);function P(a,b,c){this.i=c===Ra?a:""}P.prototype.h=!0;P.prototype.g=function(){return this.i.toString()};P.prototype.toString=function(){return this.i.toString()};var Ra={};function Sa(a,b,c,d){a=a instanceof M?a:Pa(a);b=b||q;c=c instanceof L?c instanceof L&&c.constructor===L&&c.j===La?c.i:"type_error:Const":c||"";return void 0!==d?b.open(O(a),c,d,void 0):b.open(O(a),c)};var Ta=J("Trident")||J("MSIE"),Ua=J("Edge")||Ta,Va=J("Gecko")&&!(-1!=I.toLowerCase().indexOf("webkit")&&!J("Edge"))&&!(J("Trident")||J("MSIE"))&&!J("Edge"),Wa=J("Macintosh");var Xa=function(){if(!q.addEventListener||!Object.defineProperty)return!1;var a=!1,b=Object.defineProperty({},"passive",{get:function(){a=!0}});try{q.addEventListener("test",r,b),q.removeEventListener("test",r,b)}catch(c){}return a}();function Q(a,b){this.type=a;this.target=b;this.i=!1}Q.prototype.g=function(){this.i=!0};function R(a){Q.call(this,a?a.type:"");this.relatedTarget=this.target=null;this.button=this.screenY=this.screenX=this.clientY=this.clientX=0;this.key="";this.metaKey=this.shiftKey=this.altKey=this.ctrlKey=!1;this.state=null;this.pointerId=0;this.pointerType="";this.h=null;if(a){var b=this.type=a.type,c=a.changedTouches&&a.changedTouches.length?a.changedTouches[0]:null;this.target=a.target||a.srcElement;var d=a.relatedTarget;if(d){if(Va){a:{try{w(d.nodeName);var e=!0;break a}catch(f){}e=!1}e||(d=null)}}else"mouseover"==
b?d=a.fromElement:"mouseout"==b&&(d=a.toElement);this.relatedTarget=d;c?(this.clientX=void 0!==c.clientX?c.clientX:c.pageX,this.clientY=void 0!==c.clientY?c.clientY:c.pageY,this.screenX=c.screenX||0,this.screenY=c.screenY||0):(this.clientX=void 0!==a.clientX?a.clientX:a.pageX,this.clientY=void 0!==a.clientY?a.clientY:a.pageY,this.screenX=a.screenX||0,this.screenY=a.screenY||0);this.button=a.button;this.key=a.key||"";this.ctrlKey=a.ctrlKey;this.altKey=a.altKey;this.shiftKey=a.shiftKey;this.metaKey=
a.metaKey;this.pointerId=a.pointerId||0;this.pointerType="string"===typeof a.pointerType?a.pointerType:Ya[a.pointerType]||"";this.state=a.state;this.h=a;a.defaultPrevented&&R.m.g.call(this)}}ka(R,Q);var Ya={2:"touch",3:"pen",4:"mouse"};R.prototype.g=function(){R.m.g.call(this);var a=this.h;a.preventDefault?a.preventDefault():a.returnValue=!1};var S="closure_listenable_"+(1E6*Math.random()|0);var Za=0;function $a(a,b,c,d,e){this.listener=a;this.g=null;this.src=b;this.type=c;this.capture=!!d;this.i=e;this.key=++Za;this.h=this.o=!1}function ab(a){a.h=!0;a.listener=null;a.g=null;a.src=null;a.i=null};function T(a){this.src=a;this.g={};this.h=0}T.prototype.add=function(a,b,c,d,e){var f=a.toString();a=this.g[f];a||(a=this.g[f]=[],this.h++);var g;a:{for(g=0;g<a.length;++g){var k=a[g];if(!k.h&&k.listener==b&&k.capture==!!d&&k.i==e)break a}g=-1}-1<g?(b=a[g],c||(b.o=!1)):(b=new $a(b,this.src,f,!!d,e),b.o=c,a.push(b));return b};var U="closure_lm_"+(1E6*Math.random()|0),V={},bb=0;function cb(a,b,c,d,e){if(d&&d.once)return db(a,b,c,d,e);if(Array.isArray(b)){for(var f=0;f<b.length;f++)cb(a,b[f],c,d,e);return null}c=eb(c);return a&&a[S]?a.g(b,c,t(d)?!!d.capture:!!d,e):fb(a,b,c,!1,d,e)}
function fb(a,b,c,d,e,f){if(!b)throw Error("Invalid event type");var g=t(e)?!!e.capture:!!e,k=gb(a);k||(a[U]=k=new T(a));c=k.add(b,c,d,g,f);if(c.g)return c;d=hb();c.g=d;d.src=a;d.listener=c;if(a.addEventListener)Xa||(e=g),void 0===e&&(e=!1),a.addEventListener(b.toString(),d,e);else if(a.attachEvent)a.attachEvent(ib(b.toString()),d);else if(a.addListener&&a.removeListener)a.addListener(d);else throw Error("addEventListener and attachEvent are unavailable.");bb++;return c}
function hb(){function a(c){return b.call(a.src,a.listener,c)}var b=jb;return a}function db(a,b,c,d,e){if(Array.isArray(b)){for(var f=0;f<b.length;f++)db(a,b[f],c,d,e);return null}c=eb(c);return a&&a[S]?a.h(b,c,t(d)?!!d.capture:!!d,e):fb(a,b,c,!0,d,e)}
function kb(a){if("number"!==typeof a&&a&&!a.h){var b=a.src;if(b&&b[S])b.i(a);else{var c=a.type,d=a.g;b.removeEventListener?b.removeEventListener(c,d,a.capture):b.detachEvent?b.detachEvent(ib(c),d):b.addListener&&b.removeListener&&b.removeListener(d);bb--;if(c=gb(b)){d=a.type;if(d in c.g){var e=c.g[d],f=za(e,a),g;(g=0<=f)&&Array.prototype.splice.call(e,f,1);g&&(ab(a),0==c.g[d].length&&(delete c.g[d],c.h--))}0==c.h&&(c.src=null,b[U]=null)}else ab(a)}}}
function ib(a){return a in V?V[a]:V[a]="on"+a}function jb(a,b){if(a.h)a=!0;else{b=new R(b,this);var c=a.listener,d=a.i||a.src;a.o&&kb(a);a=c.call(d,b)}return a}function gb(a){a=a[U];return a instanceof T?a:null}var lb="__closure_events_fn_"+(1E9*Math.random()>>>0);function eb(a){if("function"===typeof a)return a;a[lb]||(a[lb]=function(b){return a.handleEvent(b)});return a[lb]};function W(a){H.call(this);this.l=a;this.i={}}ka(W,H);var mb=[];function nb(a){Ja(a.i,function(b,c){this.i.hasOwnProperty(c)&&kb(b)},a);a.i={}}W.prototype.j=function(){W.m.j.call(this);nb(this)};W.prototype.handleEvent=function(){throw Error("EventHandler.handleEvent not implemented");};function ob(a){H.call(this);this.i=a||document.body;this.l=new W(this);a=ja(ya,this.l);this.h?a():(this.g||(this.g=[]),this.g.push(a));a=this.l;var b=this.i,c=this.s,d="click";Array.isArray(d)||(d&&(mb[0]=d.toString()),d=mb);for(var e=0;e<d.length;e++){var f=cb(b,d[e],c||a.handleEvent,!1,a.l||a);if(!f)break;a.i[f.key]=f}}m(ob,H);
ob.prototype.s=function(a){if(!(0!=a.h.button||Wa&&a.ctrlKey||a.i))for(var b=a.target;b&&b!=this.i;){if(b.tagName&&"a"==b.tagName.toLowerCase()){var c=b.getAttribute("href")||b.getAttributeNS("http://www.w3.org/1999/xlink","href"),d=c;try{var e=wa(c),f;if(f="www.google.com"===G(e[3],!0)){var g=wa(c);f="/url"===G(g[5],!0)}if(f){var k=xa(c,"q");d=k?k:xa(c,"url")}}catch(v){a:{var p=v;if(null!=p){var n=p.v;if(null!=n){v=n;break a}}if(p instanceof TypeError){var C=n=new ra;C.l=y(p);qa(C);n.g="__noinit__";
n.g=p;n.i(new TypeError(n));p=n}else C=n=new E,C.l=y(p),qa(C),n.g="__noinit__",n.g=p,n.i(Error(n)),p=n;v=p}if(!(v instanceof B))throw v.h;}d=null!=d?d:"";if(c!=d){e=void 0;b={target:"_blank",noreferrer:!0};c=window;d instanceof M?f=d:(f="undefined"!=typeof d.href?d.href:String(d),f instanceof M||(f="object"==typeof f&&f.h?f.g():String(f),Oa.test(f)?f=new M(f,N):(f=String(f),f=f.replace(/(%0A|%0D)/g,""),f=(g=f.match(Na))&&Ma.test(g[1])?new M(f,N):null)),f=f||Qa);d=b.target||d.target;g=[];for(e in b)switch(e){case "width":case "height":case "top":case "left":g.push(e+
"="+b[e]);break;case "target":case "noopener":case "noreferrer":break;default:g.push(e+"="+(b[e]?1:0))}e=g.join(",");if((J("iPhone")&&!J("iPod")&&!J("iPad")||J("iPad")||J("iPod"))&&c.navigator&&c.navigator.standalone&&d&&"_self"!=d)e="A",g=document,e=String(e),"application/xhtml+xml"===g.contentType&&(e=e.toLowerCase()),g=e=g.createElement(e),f=f instanceof M?f:Pa(f),g.href=O(f),e.setAttribute("target",d),b.noreferrer&&e.setAttribute("rel","noreferrer"),b=document.createEvent("MouseEvent"),b.initMouseEvent("click",
!0,!0,c,1),e.dispatchEvent(b);else if(b.noreferrer){if(c=Sa("",c,d,e),b=O(f),c){Ua&&-1!=b.indexOf(";")&&(b="'"+b.replace(/'/g,"%27")+"'");c.opener=null;Ga.test(b)&&(-1!=b.indexOf("&")&&(b=b.replace(Aa,"&amp;")),-1!=b.indexOf("<")&&(b=b.replace(Ba,"&lt;")),-1!=b.indexOf(">")&&(b=b.replace(Ca,"&gt;")),-1!=b.indexOf('"')&&(b=b.replace(Da,"&quot;")),-1!=b.indexOf("'")&&(b=b.replace(Ea,"&#39;")),-1!=b.indexOf("\x00")&&(b=b.replace(Fa,"&#0;")));b='<meta name="referrer" content="no-referrer"><meta http-equiv="refresh" content="0; url='+
b+'">';if(void 0===K)if(d=null,(e=q.trustedTypes)&&e.createPolicy){try{d=e.createPolicy("goog#html",{createHTML:u,createScript:u,createScriptURL:u})}catch(v){q.console&&q.console.error(v.message)}K=d}else K=d;b=(d=K)?d.createHTML(b):b;b=new P(b,null,Ra);(c=c.document)&&c.write&&(c.write(b instanceof P&&b.constructor===P?b.i:"type_error:SafeHtml"),c.close())}}else(c=Sa(f,c,d,e))&&b.noopener&&(c.opener=null);a.g();break}}b=b.parentNode}};function pb(a){new ob(a)}
var X=["DOCS_installLinkReferrerSanitizer"],Y=q;X[0]in Y||"undefined"==typeof Y.execScript||Y.execScript("var "+X[0]);for(var Z;X.length&&(Z=X.shift());)X.length||void 0===pb?Y[Z]&&Y[Z]!==Object.prototype[Z]?Y=Y[Z]:Y=Y[Z]={}:Y[Z]=pb;}).call(this);
</script><script type="text/javascript" nonce="">DOCS_installLinkReferrerSanitizer();</script></body></html>